'''
    A python script to generate Junit testcases.
    These testcases are to test lexer keywords.
    @author: Shao-Chua Wang
    @Date: Apr. 10, 2011
'''
import os, sys
import re
javaTemplate = """
package frontend.test;

import java.io.StringReader;
import static org.junit.Assert.*;
import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import frontend.Lexer;
import frontend.Parser; /* for token constants */

public class RegExp%(name)sTest {
	Lexer lexer;
	Parser parser;
	@Before
	public void setUp() throws Exception {
	
	}

	@After
	public void tearDown() throws Exception {
		
	}

	@Test
	public void testScan() throws Exception {
            int token;
%(testcode)s
	}

}
"""
caseTest=r'''
		token = new Lexer(
				new StringReader("%s\n"),
				new Parser()
				).yylex();
		Assert.assertEquals(token, Parser.%s);
'''
testSuiteCode="""
package frontend.test;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({
	%s
})
public class TestSuite%s {
}
"""

def printHelp():
    print """
    Usage:
        $ python %s <yacc_filename.lex> [-o output_folder]
    """ % (sys.argv[0])

def getLexFileName():
    if len(sys.argv) == 1 or not sys.argv[-1].endswith('lex'):
        printHelp()
        exit()
    return sys.argv[-1]

def getOutputFolder():
    if '-o' in sys.argv:
        return sys.argv[sys.argv.index('-o')+1]
    else:
        return ''

def genTestCases(name, cases):
    foutName = 'RegExp%sTest.java' % (name,)
    testCodes = []
    for c in cases:
        testCodes.append(caseTest % (c.strip(), name.upper()))
    testCode = ''.join(testCodes)
    outputFolder = getOutputFolder()
    fout = open(os.path.join(outputFolder, foutName), 'w')
    print >> fout, javaTemplate % {
            'name':name,
            'testcode':testCode,
        }
    fout.close()

def genTestSuite(suiteName, caseNames):
    addPrefix = lambda s: 'RegExp'+s
    addSufix = lambda s: s+'Test'
    caseNames = map(addPrefix, map(addSufix, caseNames))
    appendClass = lambda x:x+'.class'
    code = testSuiteCode % (',\n\t'.join(map(appendClass, caseNames)),
        suiteName)
    outputFolder = getOutputFolder()
    foutName = os.path.join(outputFolder, 'TestSuite%s.java' % (suiteName,))
    fout = open(foutName, 'w')
    print >> fout, code
    fout.close()

def main():
    lexFileName = getLexFileName()
    pat = re.compile("[A-Z]+\s*=\s*[@\w]+[\w| ]*")
    fp = open(lexFileName)
    s = fp.read()
    matches = pat.findall(s)
    names = []
    for m in matches:
        k,v = m.split('=')
        name = k.strip().capitalize()
        genTestCases(name, v.split('|'))
        names.append(name)
    genTestSuite('ScannerKeywords',names)
    fp.close()

if __name__ == '__main__':
    main()
